#region Copyright
/// <copyright>
/// Copyright (c) 2007 Ilia Shramko.
/// Released under the terms of the GNU General Public License.
/// </copyright>
#endregion

using System;
using System.Collections.Generic;
using System.Text;

namespace Osh.Teletext
{
	public class TeletextService
	{
		private Charset _defaultCharset;
		private TeletextMagazine[] _magazines;
		private List<NonDisplayablePacket> _servicePackets;

		public TeletextService() : this(Charset.LatinEnglish)
		{
		}

		public TeletextService(Charset defaultCharset)
		{
			this.DefaultCharset = defaultCharset;
			Initialize();
		}

		public void Clear()
		{
			Initialize();
			OnMagazineRemoveAll();
		}

		public void Initialize()
		{
			_magazines = new TeletextMagazine[TeletextMagazine.MaxMagazineNumber - TeletextMagazine.MinMagazineNumber + 1];
			_servicePackets = new List<NonDisplayablePacket>();
		}

		public Charset DefaultCharset
		{
			get { return _defaultCharset; }
			set
			{
				if(value.IsVirtual)
					throw new ArgumentOutOfRangeException("DefaultCharset", "Default charset cannot be virtual.");
				_defaultCharset = value;
			}
		}

		public TeletextMagazine[] Magazines
		{
			get { return _magazines; }
		}

		/// <summary>
		/// Returns initial page address of the service.
		/// If no page is specified or has been received then the page address PageAddress.Null (FF:3F7F) is returned.
		/// </summary>
		public PageAddress InitialPageAddress
		{
			get
			{
				foreach(NonDisplayablePacket packet in _servicePackets)
				{
					if(packet is PacketS30Format1)
						return (packet as PacketS30Format1).InitialPageAddress;
					else if(packet is PacketS30Format2)
						return (packet as PacketS30Format2).InitialPageAddress;
				}
				return PageAddress.Null;
			}
		}

		public bool TryGetMagazine(int magazineNumber, out TeletextMagazine magazine)
		{
			if(_magazines[magazineNumber] != null)
			{
				magazine = _magazines[magazineNumber];
				return true;
			}
			magazine = null;
			return false;
		}

		public bool TryGetPage(PageAddress pageAddress, out TeletextPage page)
		{
			TeletextMagazine magazine;
			if(TryGetMagazine(pageAddress.Magazine, out magazine))
				return magazine.TryGetPage(pageAddress, out page);

			page = null;
			return false;
		}

		public void AddMagazine(TeletextMagazine magazine)
		{
			if(_magazines[magazine.Number] != null)
				throw new ArgumentOutOfRangeException("magazineIndex",
					string.Format("Magazine {0} already exists.", magazine.Number));

			_magazines[magazine.Number] = magazine;
			OnMagazineAdd(magazine);
		}

		public IEnumerable<NonDisplayablePacket> ServicePackets
		{
			get { return _servicePackets; }
		}

		private int GetServicePaketIndex(int packetNumber)
		{
			for(int i = 0; i < _servicePackets.Count; i++)
				if(_servicePackets[i].Number == packetNumber)
					return i;
			return -1;
		}

		public void AddServicePacket(NonDisplayablePacket packet)
		{
			int packetIndex = GetServicePaketIndex(packet.Number);
			if(packetIndex != -1)
				_servicePackets[packetIndex] = packet;
			else
				_servicePackets.Add(packet);
		}

		protected virtual void OnMagazineAdd(TeletextMagazine magazine)
		{
			if(this.MagazineAdd != null)
				this.MagazineAdd(this, new TeletextEventArgs(this, magazine, null));
		}

		protected virtual void OnMagazineRemoveAll()
		{
			if(this.MagazineRemoveAll != null)
				this.MagazineRemoveAll(this, new TeletextEventArgs(this, null, null));
		}

		public event EventHandler<TeletextEventArgs> MagazineAdd;
		public event EventHandler<TeletextEventArgs> MagazineRemoveAll;
	}
}
